#pragma once

#include "stdafx.h"

template <class T>
class ResizeArray
{
private:
	T * _data;
	int _capacity;
	T default_val;

	void Double()
	{
		_capacity *= 2;
		T* tmp = new T[_capacity];
		for (int i = 0; i < Count; i++)
		{
			tmp[i] = _data[i];
		}
		for (int i = Count; i < _capacity; i++)
		{
			tmp[i] = default_val;
		}
		delete[] _data;
		_data = tmp;
	}

	inline void Guard()
	{
		if (_capacity == Count)
			Double();
	}

	inline void Shift(int c)
	{
		for (int i = Count - 1; i >= c; i--)
		{
			_data[i + 1] = _data[i];
		}
	}

public:
	int Count;
	ResizeArray<T>(T _default_val, int initialCapacity = 100) :
		_capacity(initialCapacity), Count(0), default_val(_default_val)
	{
		_data = new T[initialCapacity];
		for (int i = 0; i < _capacity; i++)
		{
			_data[i] = default_val;
		}
	}

	void Add(T v)
	{
		Guard();
		_data[Count++] = v;
	}

	void InsertAt(int n, T v)
	{
		if (n > Count)
		{
			throw "Index must be lower equal than Count";
			return;
		}

		Guard();
		Shift(n);
		Count++;
		_data[n] = v;
	}

	inline const T& operator[](const int i)
	{
		if (i >= Count)
		{
			throw "Index must be lower than Count";
		}
		return _data[i];
	}


	inline T operator[](const int i) const
	{
		return _data[i];
	}

	void Diagnostic()
	{
		std::cout << "Count: " << Count << ";\n";
		std::cout << "Capacity: " << _capacity << ";\n";
		for (int i = 0; i < Count; i++)
		{
			std::cout << "Element at: " << i << " Value: " << _data[i] << ";\n";
		}
		std::cout << "Defaults---------------------------------------------------------------\n";
		for (int i = Count; i < _capacity; i++)
		{
			std::cout << "Element at: " << i << " Value: " << _data[i] << ";\n";
		}
		std::cout << "End Diagnostic: \n\n\n";
	}

};